home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UCRASM25.ARJ / SCANF.ASM < prev    next >
Assembly Source File  |  1991-10-12  |  11KB  |  529 lines

  1. StdGrp        group    stdlib,stddata
  2. stddata        segment    para public 'sldata'
  3. stddata        ends
  4. ;
  5. stdlib        segment    para public 'slcode'
  6.         assume    cs:stdgrp
  7.         extrn sl_print:far,sl_putw:far, sl_putcr:far
  8. print    macro
  9.  call sl_print
  10.   endm
  11. ;
  12.         extrn    sl_getsm:far, sl_free:far, sl_atoi2:far
  13.         extrn    sl_atou2:far, sl_atol2:far, sl_atoul2:far
  14.         extrn    sl_atoh2:far
  15. ;
  16. ;
  17. ; Scanf- Like the "C" routine by the same name.  Calling sequence:
  18. ;
  19. ;               call    scanf
  20. ;               db      "format string",0
  21. ;               dd      item1, item2, ..., itemn
  22. ;
  23. ; The format string is identical to "C".  Item1..Itemn are pointers to
  24. ; values to print for this string.  Each item must be matched by the
  25. ; corresponding "%xxx" item in the format string.
  26. ;
  27. ; Format string format:
  28. ;
  29. ; 1)    If a non-whitespace character in the format string matches the next
  30. ;    input character, scanf eats that input character;  otherwise scanf
  31. ;    ignores the character in the format string.  If any whitespace char-
  32. ;    acter appears, scanf ignores all leading whitespace characters (new-
  33. ;    line not included) before an item.  If there is no whitespace on the
  34. ;    input, scanf ignores the whitespace characters in the input stream.
  35. ;
  36. ; 2)    Format Control Strings:
  37. ;
  38. ;    General format:  "%^f" where:
  39. ;
  40. ;                ^ = ^
  41. ;                f = a format character
  42. ;
  43. ;            The "^" is optional.
  44. ;
  45. ;    ^ present    The address associated with f is the address of a
  46. ;                pointer to the object, not the address of
  47. ;                the object itself.  The pointer is a far ptr.
  48. ;
  49. ;    f is one of the following
  50. ;
  51. ;        d -    Read a signed integer in decimal notation.
  52. ;        i -    Read a signed integer in decimal notation.
  53. ;        x -    Read a word value in hexadecimal notation.
  54. ;        h -    Read a byte value in hexadecimal notation.
  55. ;        u -    Read an unsigned integer in decimal notation.
  56. ;        c -    Read a character.
  57. ;        s -    Read a string.
  58. ;
  59. ;        ld-    Read a long signed integer.
  60. ;        li-    Read a long signed integer.
  61. ;        lx-    Read a long hexadecimal number.
  62. ;        lu-    Read a long unsigned number.
  63. ;
  64. ;
  65. ;    Calling Sequence:
  66. ;
  67. ;        call    Scanf
  68. ;        db    "Format String",0
  69. ;        dd    adrs1, adrs2, ..., adrsn
  70. ;
  71. ;    Where the format string is ala "C" (and the descriptions above)
  72. ;    and adrs1..adrsn are addresses (far ptr) to the items to print.
  73. ;    Unless the "^" modifier is present, these addresses are the actual
  74. ;    addresses of the objects to print.
  75. ;
  76. ; Note: Scanf always calls GETS to read a new string from the standard
  77. ;    input device.  Reading a string variable always reads all input
  78. ;    from the current position to the end of the current line.
  79. ;
  80. ;
  81. cr        equ    0dh
  82. ff        equ    0ch
  83. lf        equ    0ah
  84. tab        equ    09h
  85. bs        equ    08h
  86. ;
  87. RtnAdrs        equ    <2[bp]>
  88. OprndPtr    equ    <(0-4)[bp]>
  89. InputPtr    equ    <(0-8)[bp]>
  90. InpIndex    equ    <(0-10)[bp]>
  91. ;
  92.         public  sl_scanf
  93. sl_scanf    proc    far
  94. ;
  95. ; Read a line from the standard input and save away a pointer to it.
  96. ;
  97.         push    bp
  98.         mov    bp, sp
  99.         sub    sp, 10            ;Save ptr to operands here.
  100.         pushf
  101.         push    ax
  102.         push    bx
  103.         push    cx
  104.         push    dx
  105.         push    di
  106.         push    si
  107.         push    es
  108.         push    ds
  109. ;
  110.         call    sl_getsm
  111.         call    scanf
  112.         les    di, InputPtr
  113.         call    sl_free
  114.         mov    di, OprndPtr
  115.         mov    RtnAdrs, di    ;Put out new return address.
  116. ;
  117.         pop    ds
  118.         pop    es
  119.         pop    si
  120.         pop    di
  121.         pop    dx
  122.         pop    cx
  123.         pop    bx
  124.         pop    ax
  125.         popf
  126.         mov    sp, bp        ;Remove local variables.
  127.         pop    bp
  128.         ret
  129. ;
  130. sl_scanf    endp
  131. ;
  132. ;
  133. ; SSCANF-    Just like SCANF except you pass a pointer to the data
  134. ;        string in es:di rather than having scanf read it from
  135. ;        the keyboard.
  136. ;
  137.         public    sl_sscanf
  138. sl_sscanf    proc    far
  139.         push    bp
  140.         mov    bp, sp
  141.         sub    sp, 10            ;Save ptr to operands here.
  142.         pushf
  143.         push    ax
  144.         push    bx
  145.         push    cx
  146.         push    dx
  147.         push    di
  148.         push    si
  149.         push    es
  150.         push    ds
  151. ;
  152.         call    scanf
  153.         mov    di, OprndPtr
  154.         mov    RtnAdrs, di    ;Put out new return address.
  155. ;
  156.         pop    ds
  157.         pop    es
  158.         pop    si
  159.         pop    di
  160.         pop    dx
  161.         pop    cx
  162.         pop    bx
  163.         pop    ax
  164.         popf
  165.         mov    sp, bp        ;Remove local variables.
  166.         pop    bp
  167.         ret
  168. sl_sscanf    endp
  169. ;
  170. ;
  171. ; "Guts" of the scanf routines.
  172. ;
  173. scanf        proc    near
  174.         mov    InputPtr+2, es        ;Sock away ptr to string.
  175.         mov    InputPtr, di
  176.         mov    word ptr InpIndex, 0
  177. ;
  178. ;
  179. ; Get pointers to the return address (format string).
  180. ;
  181.         cld
  182.         les    di, RtnAdrs
  183.         lds    si, RtnAdrs
  184. ;
  185. ; Okay, search for the end of the format string.  After these instructions,
  186. ; di points just beyond the zero byte at the end of the format string.  This,
  187. ; of course, points at the first address beyond the format string.
  188. ;
  189.         mov    al, 0
  190.         mov    cx, 65535
  191.     repne    scasb
  192.         mov     OprndPtr, di
  193.         mov    OprndPtr+2, es
  194. ;
  195. ScanItems:      lodsb            ;Get char si points at.
  196. ScanItems2:    cmp    al, 0        ;EOS?
  197.         jz    ScanfDone
  198.         cmp    al, "%"        ;Start of a format string?
  199.         jz    FmtItem
  200. SkipIt:        cmp    al, " "
  201.         jz    SkipWS
  202.         les    di, InputPtr
  203.         mov    bx, InpIndex
  204.         cmp    al, es:[di][bx]
  205.         jnz    ScanItems
  206.         inc    word ptr InpIndex
  207.         jmp    ScanItems
  208. ;
  209. SkipWS:        les    di, InputPtr
  210.         mov    bx, InpIndex
  211. SkipWSLp:    cmp    byte ptr es:[di][bx], ' '
  212.         jnz    DoneSkip
  213.         inc    bx
  214.         jmp    SkipWSLp
  215. ;
  216. DoneSkip:    mov    InpIndex, bx
  217. Skip2:        lodsb
  218.         cmp    al, ' '            ;Skip additional whitespace
  219.         jz    Skip2            ; in the format string.
  220.         dec    si
  221.         jmp    ScanItems
  222. ;
  223. ;
  224. FmtItem:    call    GetFmtItem    ;Process the format item here.
  225.         jmp    ScanItems
  226. ;
  227. ;
  228. ScanfDone:        ret
  229. scanf        endp
  230. ;
  231. ;
  232. ;
  233. ; If we just saw a "%", come down here to handle the format item.
  234. ;
  235. GetFmtItem    proc    near
  236. ;
  237.         lodsb                ;Get char beyond "%"
  238. ;
  239. ; See if the user wants to specify a handle rather than a straight pointer
  240. ;
  241.         cmp    al, '^'
  242.         jne     ChkFmtChars
  243.         mov    ah, al
  244.         lodsb                ;Skip "^" character
  245. ;
  246. ; Okay, process the format characters down here.
  247. ;
  248. ChkFmtChars:    and    al, 05fh        ;l.c. -> U.C.
  249.         cmp    al, 'D'
  250.         je    GetDec
  251.         cmp    al, 'I'
  252.         je    GetDec
  253.         cmp    al, 'C'
  254.         je    GetChar
  255. ;
  256.         cmp    al, 'X'
  257.         jne    TryH
  258.         jmp    GetHexWord
  259. ;
  260. TryH:        cmp    al, 'H'
  261.         jne    TryU
  262.         jmp    GetHexByte
  263. ;
  264. TryU:        cmp    al, 'U'
  265.         jne    TryString
  266.         jmp    GetUDec
  267. ;
  268. TryString:    cmp    al, 'S'
  269.         jne    TryLong
  270.         jmp    GetString
  271. ;
  272. TryLong:    cmp    al, 'L'
  273.         jne    Default
  274. ;
  275. ; If we've got the "L" modifier, this is a long value to print, get the
  276. ; data type character as the next value:
  277. ;
  278.         lodsb
  279.         and    al, 05fh        ;l.c. -> U.C.
  280.         cmp    al, 'D'
  281.         je    JmpDec
  282.         cmp    al, 'I'
  283.         jne    TryLU
  284. JmpDec:        jmp    LongDec
  285. ;
  286. TryLU:        cmp    al, 'U'
  287.         jne    Default
  288.         jmp    LongU
  289. ;
  290. ;
  291. ;
  292. ; If none of the above, simply return without printing anything.
  293. ;
  294. Default:    ret
  295. ;
  296. ;
  297. ;
  298. ;
  299. ;
  300. ; Get a signed decimal value here.
  301. ;
  302. GetDec:        call    GetPtr            ;Get next pointer into ES:BX
  303.         push    ax            ;Save possible "^" char in ah
  304.         push    es
  305.         les    di, InputPtr
  306.         add    di, InpIndex        ;Point SI at integer.
  307.         cmp    byte ptr es:[di], 0    ;At end of string?
  308.         jz    QuitGetDec
  309.         call    sl_atoi2        ;Convert to integer in AX.
  310.         sub    di, InputPtr
  311.         mov    InpIndex, di
  312.         pop    es                 ; Ignore overflow or error.
  313.         mov    es:[bx], ax
  314. ;
  315.         pop    ax
  316.         ret
  317. ;
  318. QuitGetDec:    pop    es
  319.         pop    ax
  320.         ret                ;We're done!
  321. ;
  322. ;
  323. ;
  324. ; Print a character variable here.
  325. ;
  326. GetChar:    call    GetPtr            ;Get next pointer into ES:BX
  327.         push    ax            ;Save possible "^" char in ah
  328.         push    es
  329.         les    di, InputPtr
  330.         add    di, InpIndex        ;Point SI at char.
  331.         mov    al, es:[di]        ;Get char
  332.         cmp    al, 0            ;See if at EOS.
  333.         jz    QuitGetChar
  334.         inc    word ptr InpIndex    ;Bump up index.
  335.         pop    es             
  336.         mov    es:[bx], al
  337. ;
  338.         pop    ax
  339.         ret
  340. ;
  341. QuitGetChar:    pop    es
  342.         pop    ax
  343.         ret                ;We're done!
  344. ;
  345. ;
  346. ;
  347. ; Print a hexadecimal word value here.
  348. ;
  349. GetHexWord:    call    GetPtr            ;Get next pointer into ES:BX
  350.         push    ax            ;Save possible "^" char in ah
  351.         push    es
  352.         les    di, InputPtr
  353.         add    di, InpIndex        ;Point SI at integer.
  354.         cmp    byte ptr es:[di], 0    ;Check for EOS
  355.         jz    QuitGetHexWord
  356.         call    sl_atoh2        ;Convert to integer in AX.
  357.         sub    di, InputPtr
  358.         mov    InpIndex, di
  359.         pop    es                 ; Ignore overflow or error.
  360.         mov    es:[bx], ax
  361. ;
  362.         pop    ax
  363.         ret
  364. ;
  365. QuitGetHexWord:    pop    es
  366.         pop    ax
  367.         ret                ;We're done!
  368. ;
  369. ;
  370. ;
  371. ;
  372. ; Print hex bytes here.
  373. ;
  374. ;
  375. GetHexByte:    call    GetPtr            ;Get next pointer into ES:BX
  376.         push    ax            ;Save possible "^" char in ah
  377.         push    es
  378.         les    di, InputPtr
  379.         add    di, InpIndex        ;Point SI at integer.
  380.         cmp    byte ptr es:[di], 0    ;Check for EOS.
  381.         jz    QuitGetHexByte
  382.         call    sl_atoh2        ;Convert to integer in AX.
  383.         sub    di, InputPtr
  384.         mov    InpIndex, di
  385.         pop    es                 ; Ignore overflow or error.
  386.         mov    es:[bx], al
  387. ;
  388.         pop    ax
  389.         ret
  390. ;
  391. QuitGetHexByte:    pop    es
  392.         pop    ax
  393.         ret                ;We're done!
  394. ;
  395. ;
  396. ;
  397. ; Output unsigned decimal numbers here:
  398. ;
  399. GetUDec:    call    GetPtr            ;Get next pointer into ES:BX
  400.         push    ax            ;Save possible "^" char in ah
  401.         push    es
  402.         les    di, InputPtr
  403.         add    di, InpIndex        ;Point SI at integer.
  404.         cmp    byte ptr es:[di], 0    ;Check for EOS.
  405.         jz    QuitGetUDec
  406.         call    sl_atou2        ;Convert to integer in AX.
  407.         sub    di, InputPtr
  408.         mov    InpIndex, di
  409.         pop    es                 ; Ignore overflow or error.
  410.         mov    es:[bx], ax
  411. ;
  412.         pop    ax
  413.         ret
  414. ;
  415. QuitGetUDec:    pop    es
  416.         pop    ax
  417.         ret                ;We're done!
  418. ;
  419. ;
  420. ; Output a string here:
  421. ;
  422. GetString:    push    ax
  423.         push    si
  424.         push    es
  425.         push    ds
  426. ;
  427.         call    GetPtr
  428.         mov    di, bx
  429.         lds    si, InputPtr
  430.         add    si, InpIndex
  431. GetStrLp:    lodsb            ;Get next char
  432.         stosb
  433.         cmp    al, 0
  434.         jnz    GetStrLp
  435.         sub    si, InputPtr
  436.         dec    si
  437.         mov    InpIndex, si
  438. ;
  439.         pop    ds
  440.         pop    es
  441.         pop    si
  442.         pop    ax
  443.         ret                ;We're done!
  444. ;
  445. ;
  446. ;
  447. ; Print a signed long decimal value here.
  448. ;
  449. LongDec:    push    dx
  450.         call    GetPtr            ;Get next pointer into ES:BX
  451.         push    ax            ;Save possible "^" char in ah
  452.         push    es
  453.         les    di, InputPtr
  454.         add    di, InpIndex        ;Point SI at integer.
  455.         cmp    byte ptr es:[di], 0    ;Check for EOS.
  456.         jz    QuitLongDec
  457.         call    sl_atol2        ;Convert to integer in AX.
  458.         sub    di, InputPtr
  459.         mov    InpIndex, di
  460.         pop    es                 ; Ignore overflow or error.
  461.         mov    es:[bx], ax
  462.         mov    es:2[bx], dx
  463. ;
  464.         pop    ax
  465.         pop    dx
  466.         ret                ;We're done!
  467. ;
  468. QuitLongDec:    pop    es
  469.         pop    ax
  470.         pop    dx
  471.         ret
  472. ;
  473. ;
  474. ;
  475. ; Print an unsigned long decimal value here.
  476. ;
  477. LongU:        push    dx
  478.         call    GetPtr            ;Get next pointer into ES:BX
  479.         push    ax            ;Save possible "^" char in ah
  480.         push    es
  481.         les    di, InputPtr
  482.         add    di, InpIndex        ;Point SI at integer.
  483.         cmp    byte ptr es:[di], 0
  484.         je    QuitLongU
  485.         call    sl_atoul2        ;Convert to integer in AX.
  486.         sub    di, InputPtr
  487.         mov    InpIndex, di
  488.         pop    es                 ; Ignore overflow or error.
  489.         mov    es:[bx], ax
  490.         mov    es:2[bx], dx
  491. ;
  492.         pop    ax
  493.         pop    dx
  494.         ret                ;We're done!
  495. ;
  496. QuitLongU:    pop    es
  497.         pop    ax
  498.         pop    dx
  499.         ret
  500. ;
  501. GetFmtItem    endp
  502. ;
  503. ;
  504. ;
  505. ;
  506. ;
  507. ;
  508. ; GetPtr- Grabs the next pointer which OprndPtr points at and returns this
  509. ;      far pointer in ES:BX.
  510. ;
  511. GetPtr        proc    near
  512.         les    di, OprndPtr
  513.         les    bx, es:[di]
  514.         add    word ptr OprndPtr, 4
  515. ;
  516. ; See if this is a handle rather than a pointer.
  517. ;
  518.         cmp    ah, '^'
  519.         jne    NotHandle
  520.         les    bx, es:[bx]
  521. NotHandle:    ret
  522. GetPtr        endp
  523. ;
  524. ;
  525. ;
  526. ;
  527. stdlib        ends
  528.         end
  529.